package net.kaaass.tools.gradequery;

import javafx.util.Pair;
import net.kaaass.tools.gradequery.network.Query;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;

import javax.swing.*;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

public class ThreadPool {
    private static final int POOL_SIZE = 30;
    private static final int PER_TASK = 10;
    private static ThreadPool threadPool = null;
    private static boolean lock = false;

    private static String[] s1 = {"语", "数", "英", "物", "化", "生", "政", "史", "地", "技"};
    private static String[] s2 = {"英", "物", "化", "生", "政", "史", "地", "技"};

    int done = 0;
    int total = 1;
    List<Pair<String, String>> data = null;
    MainForm mainForm;

    private ThreadPool() {
    }

    public static ThreadPool init() {
        if (threadPool == null && !lock) {
            lock = true;
            threadPool = new ThreadPool();
            lock = false;
        }
        return threadPool;
    }

    public void loadIn(List<Pair<String, String>> data) {
        this.data = data;
    }

    public void start(MainForm mainForm) throws IOException {
        this.mainForm = mainForm;
        done = 0;
        MainForm.updateProg(mainForm, 0);
        ExecutorService service = Executors.newFixedThreadPool(POOL_SIZE);
        List<Future<List<Mark>>> future = new ArrayList<>();
        for (int i = 0; i <= data.size() / PER_TASK; i++) {
            int rest = data.size() - PER_TASK * i;
            if (rest < PER_TASK) {
                future.add(service.submit(new QueryTask(data, PER_TASK * i, rest)));
            } else {
                future.add(service.submit(new QueryTask(data, PER_TASK * i, PER_TASK)));
            }
        }
        this.total = future.size();
        this.onEnd(future);
    }

    private void onEnd(List<Future<List<Mark>>> future) throws IOException {
        List<Mark> d = new ArrayList<>();
        for (int i = 0; i < future.size(); i++) {
            Future<List<Mark>> f = future.get(i);
            try {
                d.addAll(f.get());
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
                throw new IllegalArgumentException(e);
            }
        }
        /*
         生成结果保存
         */
        MainForm.updateTip(mainForm, "查询完毕，正在生成结果");
        if (MainForm.fOutput.exists()) // 如果文件已经存在就删除
            MainForm.fOutput.delete();
        MainForm.fOutput.createNewFile();
        this.createDataTable(MainForm.fOutput, d);
        /*
        结束
         */
        MainForm.updateTip(mainForm, "完毕");
        JOptionPane.showMessageDialog(null, "查询完毕！供查询数据：" + data.size());
        MainForm.end(mainForm);
    }

    public void createDataTable(File fOutput, List<Mark> d) throws IOException {
        HSSFWorkbook workbook = new HSSFWorkbook();
        HSSFSheet sheet = workbook.createSheet("查询结果");
        int rowCount = 0;
        /*
        设置列宽
         */
        /*
        sheet.setColumnWidth(0, 8);
        sheet.setColumnWidth(1, 11);
        sheet.setColumnWidth(2, 20);
        sheet.setColumnWidth(3, 10);
        for (int i = 4; i <= 21; i++)
            sheet.setColumnWidth(i, 3);
        */
        /*
        头
         */
        HSSFCellStyle jz = workbook.createCellStyle();
        jz.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        jz.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);

        HSSFRow row = sheet.createRow(rowCount);
        CellRangeAddress cells = new CellRangeAddress(rowCount, rowCount + 1, 0, 21);
        sheet.addMergedRegion(cells);
        HSSFCell cell = row.createCell(0);
        cell.setCellValue("学考成绩查询结果");
        HSSFCellStyle style = workbook.createCellStyle();
        HSSFFont font = workbook.createFont();
        font.setFontHeightInPoints((short) 20);
        font.setBold(true);
        style.setFont(font);
        style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
        cell.setCellStyle(style);
        rowCount += 2;

        row = sheet.createRow(rowCount);
        cells = new CellRangeAddress(rowCount, rowCount, 0, 21);
        sheet.addMergedRegion(cells);
        cell = row.createCell(0);
        cell.setCellValue("本文件由学考成绩批量查询工具生成 作者：温八高 谷越");
        cell.setCellStyle(jz);
        rowCount++;
        /*
        类别
         */
        row = sheet.createRow(rowCount);
        cells = new CellRangeAddress(rowCount, rowCount + 1, 0, 0);
        sheet.addMergedRegion(cells);
        cell = row.createCell(0);
        cell.setCellValue("姓名");
        cell.setCellStyle(jz);
        cells = new CellRangeAddress(rowCount, rowCount + 1, 1, 1);
        sheet.addMergedRegion(cells);
        cell = row.createCell(1);
        cell.setCellValue("准考证号");
        cell.setCellStyle(jz);
        cells = new CellRangeAddress(rowCount, rowCount + 1, 2, 2);
        sheet.addMergedRegion(cells);
        cell = row.createCell(2);
        cell.setCellValue("身份证号");
        cell.setCellStyle(jz);
        cells = new CellRangeAddress(rowCount, rowCount + 1, 3, 3);
        sheet.addMergedRegion(cells);
        cell = row.createCell(3);
        cell.setCellValue("报名序号");
        cell.setCellStyle(jz);

        cells = new CellRangeAddress(rowCount, rowCount, 4, 13);
        sheet.addMergedRegion(cells);
        cell = row.createCell(4);
        cell.setCellValue("等第（学考）");
        cell.setCellStyle(jz);

        cells = new CellRangeAddress(rowCount, rowCount, 14, 21);
        sheet.addMergedRegion(cells);
        cell = row.createCell(14);
        cell.setCellValue("赋分（选考）");
        cell.setCellStyle(jz);

        row = sheet.createRow(rowCount + 1);
        for (int i = 0; i < s1.length; i++) {
            cell = row.createCell(i + 4);
            cell.setCellValue(s1[i]);
            cell.setCellStyle(jz);
        }
        for (int i = 0; i < s2.length; i++) {
            cell = row.createCell(i + 14);
            cell.setCellValue(s2[i]);
            cell.setCellStyle(jz);
        }
        rowCount += 2;
        /*
        数据
         */
        int ii;
        for (Mark mark : d) {
            ii = 0;
            row = sheet.createRow(rowCount++);
            cell = row.createCell(ii++);
            cell.setCellValue(mark.getName());
            cell = row.createCell(ii++);
            cell.setCellValue(mark.getExamId());
            cell = row.createCell(ii++);
            cell.setCellValue(mark.getId());
            cell = row.createCell(ii++);
            cell.setCellValue(mark.getReqId());
            for (String s : mark.getLevel()) {
                cell = row.createCell(ii++);
                cell.setCellValue(s);
            }
            for (String s : mark.getMark()) {
                cell = row.createCell(ii++);
                cell.setCellValue(s);
            }
        }
        /*
        保存
         */
        FileOutputStream fileOut = new FileOutputStream(fOutput);
        workbook.write(fileOut);
    }

    private class QueryTask implements Callable<List<Mark>> {
        List<Pair<String, String>> source;
        int offset;
        int length;

        QueryTask(List<Pair<String, String>> source, int offset, int length) {
            this.source = source.subList(offset, offset + length);
            this.offset = offset;
            this.length = length;
        }

        @Override
        public List<Mark> call() throws Exception {
            List<Mark> marks = new ArrayList<>();
            source.forEach((pair) -> {
                try {
                    System.out.format("开始查询目标：%s,%s\n", pair.getKey(), pair.getValue());
                    marks.add(Query.query(pair.getKey(), pair.getValue()));
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
            MainForm.updateProg(mainForm, ++done * 100 / total);
            return marks;
        }
    }
}
